package com.cloudree.gllib.constants;

import android.opengl.Matrix;


/**
 * Created by Administrator on 2017/8/8.
 */
public class RenderData {


    /**
     * data related to vbo cube
     */
    public static class VBO {
        public static final float[] vertexData =
                {
                        // In OpenGL counter-clockwise winding is default. This means that when we look at a triangle,
                        // if the points are counter-clockwise we are looking at the "front". If not we are looking at
                        // the back. OpenGL has an optimization where all back-facing triangles are culled, since they
                        // usually represent the backside of an object and aren't visible anyways.

                        // Front face
                        -1.0f, 1.0f, 1.0f,
                        -1.0f, -1.0f, 1.0f,
                        1.0f, 1.0f, 1.0f,
                        -1.0f, -1.0f, 1.0f,
                        1.0f, -1.0f, 1.0f,
                        1.0f, 1.0f, 1.0f,

                        // Right face
                        1.0f, 1.0f, 1.0f,
                        1.0f, -1.0f, 1.0f,
                        1.0f, 1.0f, -1.0f,
                        1.0f, -1.0f, 1.0f,
                        1.0f, -1.0f, -1.0f,
                        1.0f, 1.0f, -1.0f,

                        // Back face
                        1.0f, 1.0f, -1.0f,
                        1.0f, -1.0f, -1.0f,
                        -1.0f, 1.0f, -1.0f,
                        1.0f, -1.0f, -1.0f,
                        -1.0f, -1.0f, -1.0f,
                        -1.0f, 1.0f, -1.0f,

                        // Left face
                        -1.0f, 1.0f, -1.0f,
                        -1.0f, -1.0f, -1.0f,
                        -1.0f, 1.0f, 1.0f,
                        -1.0f, -1.0f, -1.0f,
                        -1.0f, -1.0f, 1.0f,
                        -1.0f, 1.0f, 1.0f,

                        // Top face
                        -1.0f, 1.0f, -1.0f,
                        -1.0f, 1.0f, 1.0f,
                        1.0f, 1.0f, -1.0f,
                        -1.0f, 1.0f, 1.0f,
                        1.0f, 1.0f, 1.0f,
                        1.0f, 1.0f, -1.0f,

                        // Bottom face
                        1.0f, -1.0f, -1.0f,
                        1.0f, -1.0f, 1.0f,
                        -1.0f, -1.0f, -1.0f,
                        1.0f, -1.0f, 1.0f,
                        -1.0f, -1.0f, 1.0f,
                        -1.0f, -1.0f, -1.0f,
                };

        // R, G, B, A
        public static final float[] colorData =
                {
                        // Front face (red)
                        1.0f, 0.0f, 0.0f, 1.0f,
                        1.0f, 0.0f, 0.0f, 1.0f,
                        1.0f, 0.0f, 0.0f, 1.0f,
                        1.0f, 0.0f, 0.0f, 1.0f,
                        1.0f, 0.0f, 0.0f, 1.0f,
                        1.0f, 0.0f, 0.0f, 1.0f,

                        // Right face (green)
                        0.0f, 1.0f, 0.0f, 1.0f,
                        0.0f, 1.0f, 0.0f, 1.0f,
                        0.0f, 1.0f, 0.0f, 1.0f,
                        0.0f, 1.0f, 0.0f, 1.0f,
                        0.0f, 1.0f, 0.0f, 1.0f,
                        0.0f, 1.0f, 0.0f, 1.0f,

                        // Back face (blue)
                        0.0f, 0.0f, 1.0f, 1.0f,
                        0.0f, 0.0f, 1.0f, 1.0f,
                        0.0f, 0.0f, 1.0f, 1.0f,
                        0.0f, 0.0f, 1.0f, 1.0f,
                        0.0f, 0.0f, 1.0f, 1.0f,
                        0.0f, 0.0f, 1.0f, 1.0f,

                        // Left face (yellow)
                        1.0f, 1.0f, 0.0f, 1.0f,
                        1.0f, 1.0f, 0.0f, 1.0f,
                        1.0f, 1.0f, 0.0f, 1.0f,
                        1.0f, 1.0f, 0.0f, 1.0f,
                        1.0f, 1.0f, 0.0f, 1.0f,
                        1.0f, 1.0f, 0.0f, 1.0f,

                        // Top face (cyan)
                        0.0f, 1.0f, 1.0f, 1.0f,
                        0.0f, 1.0f, 1.0f, 1.0f,
                        0.0f, 1.0f, 1.0f, 1.0f,
                        0.0f, 1.0f, 1.0f, 1.0f,
                        0.0f, 1.0f, 1.0f, 1.0f,
                        0.0f, 1.0f, 1.0f, 1.0f,

                        // Bottom face (magenta)
                        1.0f, 0.0f, 1.0f, 1.0f,
                        1.0f, 0.0f, 1.0f, 1.0f,
                        1.0f, 0.0f, 1.0f, 1.0f,
                        1.0f, 0.0f, 1.0f, 1.0f,
                        1.0f, 0.0f, 1.0f, 1.0f,
                        1.0f, 0.0f, 1.0f, 1.0f
                };

        // X, Y, Z
        // The normal is used in light calculations and is a vector which points
        // orthogonal to the plane of the surface. For a cube model, the normals
        // should be orthogonal to the points of each face.
        public static final float[] normalData =
                {
                        // Front face
                        0.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 1.0f,

                        // Right face
                        1.0f, 0.0f, 0.0f,
                        1.0f, 0.0f, 0.0f,
                        1.0f, 0.0f, 0.0f,
                        1.0f, 0.0f, 0.0f,
                        1.0f, 0.0f, 0.0f,
                        1.0f, 0.0f, 0.0f,

                        // Back face
                        0.0f, 0.0f, -1.0f,
                        0.0f, 0.0f, -1.0f,
                        0.0f, 0.0f, -1.0f,
                        0.0f, 0.0f, -1.0f,
                        0.0f, 0.0f, -1.0f,
                        0.0f, 0.0f, -1.0f,

                        // Left face
                        -1.0f, 0.0f, 0.0f,
                        -1.0f, 0.0f, 0.0f,
                        -1.0f, 0.0f, 0.0f,
                        -1.0f, 0.0f, 0.0f,
                        -1.0f, 0.0f, 0.0f,
                        -1.0f, 0.0f, 0.0f,

                        // Top face
                        0.0f, 1.0f, 0.0f,
                        0.0f, 1.0f, 0.0f,
                        0.0f, 1.0f, 0.0f,
                        0.0f, 1.0f, 0.0f,
                        0.0f, 1.0f, 0.0f,
                        0.0f, 1.0f, 0.0f,

                        // Bottom face
                        0.0f, -1.0f, 0.0f,
                        0.0f, -1.0f, 0.0f,
                        0.0f, -1.0f, 0.0f,
                        0.0f, -1.0f, 0.0f,
                        0.0f, -1.0f, 0.0f,
                        0.0f, -1.0f, 0.0f
                };
        //texture related
        public final static float[] textureData =
                {
                        // Front face
                        0.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 1.0f,
                        1.0f, 0.0f,

                        // Right face
                        0.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 1.0f,
                        1.0f, 0.0f,

                        // Back face
                        0.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 1.0f,
                        1.0f, 0.0f,

                        // Left face
                        0.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 1.0f,
                        1.0f, 0.0f,

                        // Top face
                        0.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 1.0f,
                        1.0f, 0.0f,

                        // Bottom face
                        0.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 0.0f,
                        0.0f, 1.0f,
                        1.0f, 1.0f,
                        1.0f, 0.0f
                };
    }

    /**
     * data related to ibo map
     */
    public static class IBO {
        static final int SIZE_PER_SIDE = 32;
        static final float MIN_POSITION = -5f;
        static final float POSITION_RANGE = 10f;

        /**
         * vertex data
         */
        public static float[] vertexData(int xL, int yL, int sizePerEle) {
            float[] vertexData = new float[xL * yL * sizePerEle];

            int offset = 0;

            // First, build the data for the vertex buffer
            for (int y = 0; y < yL; y++) {
                for (int x = 0; x < xL; x++) {
                    final float xRatio = x / (float) (xL - 1);

                    // Build our heightmap from the top down, so that our triangles are counter-clockwise.
                    final float yRatio = 1f - (y / (float) (yL - 1));

                    final float xPosition = MIN_POSITION + (xRatio * POSITION_RANGE);
                    final float yPosition = MIN_POSITION + (yRatio * POSITION_RANGE);

                    // Position
                    vertexData[offset++] = xPosition;
                    vertexData[offset++] = yPosition;
                    vertexData[offset++] = ((xPosition * xPosition) + (yPosition * yPosition)) / 10f;

                    // Cheap normal using a derivative of the function.
                    // The slope for X will be 2X, for Y will be 2Y.
                    // Divide by 10 since the position's Z is also divided by 10.
                    final float xSlope = (2 * xPosition) / 10f;
                    final float ySlope = (2 * yPosition) / 10f;

                    // Calculate the normal using the cross product of the slopes.
                    final float[] planeVectorX = {1f, 0f, xSlope};
                    final float[] planeVectorY = {0f, 1f, ySlope};
                    final float[] normalVector = {
                            (planeVectorX[1] * planeVectorY[2]) - (planeVectorX[2] * planeVectorY[1]),
                            (planeVectorX[2] * planeVectorY[0]) - (planeVectorX[0] * planeVectorY[2]),
                            (planeVectorX[0] * planeVectorY[1]) - (planeVectorX[1] * planeVectorY[0])};

                    // Normalize the normal						
                    final float length = Matrix.length(normalVector[0], normalVector[1], normalVector[2]);

                    vertexData[offset++] = normalVector[0] / length;
                    vertexData[offset++] = normalVector[1] / length;
                    vertexData[offset++] = normalVector[2] / length;

                    // Add some fancy colors.
                    vertexData[offset++] = xRatio;
                    vertexData[offset++] = yRatio;
                    vertexData[offset++] = 0.5f;
                    vertexData[offset++] = 1f;
                }
            }


            return vertexData;
        }

        /**
         * index data
         */
        public static short[] indexData(int xL, int yL) {
            short[] indexData = new short[2 * xL * (yL - 1) + 2 * (yL - 1)];
            int offset = 0;

            for (int y = 0; y < yL - 1; y++) {
                if (y > 0) {
                    // Degenerate begin: repeat first vertex
                    indexData[offset++] = (short) (y * yL);
                }

                for (int x = 0; x < xL; x++) {
                    // One part of the strip
                    indexData[offset++] = (short) ((y * yL) + x);
                    indexData[offset++] = (short) (((y + 1) * yL) + x);
                }

                if (y < yL - 2) {
                    // Degenerate end: repeat last vertex
                    indexData[offset++] = (short) (((y + 1) * yL) + (xL - 1));
                }
            }

            return indexData;
        }

    }


    public static final double PAI = 3.1415926;

    /**
     * Hockey table
     */
    public static class Hockey {
        //single data
        public static final float[] vertexData = {
                //vertex data
                -0.5f, -0.5f,
                0.5f, 0.5f,
                -0.5f, 0.5f,

                -0.5f, -0.5f,
                0.5f, -0.5f,
                0.5f, 0.5f,
                //divide line
                -0.5f, 0.0f,
                0.5f, 0.0f,
                //stick
                0.0f, 0.25f,
                0.0f, -0.25f
        };

        //combined data
        public static final float[] vertexFanData = {
                //vertex data
                0.0f, 0.0f,//vertex
                1.0f, 1.0f, 1.0f, 1.0f,//color
                -0.5f, -0.8f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                0.5f, -0.8f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                0.5f, 0.8f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                -0.5f, 0.8f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                -0.5f, -0.8f,
                0.7f, 0.7f, 0.7f, 0.7f,//color

                //divide line
                -0.5f, 0.0f,
                1.0f, 0.0f, 0.0f, 1.0f,
                0.5f, 0.0f,
                1.0f, 0.0f, 0.0f, 1.0f,
                //stick
                0.0f, 0.4f,
                0.0f, 0.0f, 1.0f, 1.0f,
                0.0f, -0.4f,
                1.0f, 0.0f, 0.0f, 1.0f
        };
        // 4 components coordinates
        public static final float[] ver4Data = {
                //vertex data
                0.0f, 0.0f, 0.0f, 1.5f,//vertex
                1.0f, 1.0f, 1.0f, 1.0f,//color
                -0.5f, -0.8f, 0.0f, 1.0f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                0.5f, -0.8f, 0.0f, 1.0f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                0.5f, 0.8f, 0.0f, 2.0f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                -0.5f, 0.8f, 0.0f, 2.0f,
                0.7f, 0.7f, 0.7f, 0.7f,//color
                -0.5f, -0.8f, 0.0f, 1.0f,
                0.7f, 0.7f, 0.7f, 0.7f,//color

                //divide line
                -0.5f, 0.0f, 0.0f, 1.5f,
                1.0f, 0.0f, 0.0f, 1.0f,
                0.5f, 0.0f, 0.0f, 1.5f,
                1.0f, 0.0f, 0.0f, 1.0f,
                //stick
                0.0f, 0.4f, 0.0f, 1.75f,
                0.0f, 0.0f, 1.0f, 1.0f,
                0.0f, -0.4f, 0.0f, 1.25f,
                1.0f, 0.0f, 0.0f, 1.0f
        };

        /**
         * generate vertex fan data
         */
        public static final float[] generateFanData(double angle) {
            float[] fanData = new float[(int) ((1 + 360 / angle + 1 + 4) * 6)];
            int index = 0;
            float xAxis = 0.5f;
            float yAxis = 0.8f;
            float[] startVertex = {
                    0.0f, 0.0f,
                    1.0f, 1.0f, 1.0f, 1.0f
            };
            float[] lineVertex = {
                    -0.5f, 0.0f,
                    1.0f, 0.0f, 0.0f, 1.0f,
                    0.5f, 0.0f,
                    1.0f, 0.0f, 0.0f, 1.0f
            };
            float[] stickVertex = {
                    0.0f, 0.25f,
                    0.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, -0.25f,
                    1.0f, 0.0f, 0.0f, 1.0f
            };

            //add start point
            for (float v : startVertex) {
                fanData[index++] = v;
            }

            //

            for (int i = 0; i <= 360 / angle; i++) {
                double da = i * angle;
                double radian = da * PAI / 180;
                float cos = (float) (Math.sqrt(xAxis * xAxis + yAxis * yAxis) * Math.cos(radian));
                float sin = (float) (Math.sqrt(xAxis * xAxis + yAxis * yAxis) * Math.sin(radian));
                if (da >= 0 && da < 90) {
                    fanData[index++] = cos > xAxis ? xAxis : cos;
                    fanData[index++] = sin > yAxis ? yAxis : sin;
                }
                if (da >= 90 && da < 180) {
                    fanData[index++] = Math.abs(cos) > xAxis ? -xAxis : cos;
                    fanData[index++] = sin > yAxis ? yAxis : sin;
                }
                if (da >= 180 && da < 270) {
                    fanData[index++] = Math.abs(cos) > xAxis ? -xAxis : cos;
                    fanData[index++] = Math.abs(sin) > yAxis ? -yAxis : sin;
                }
                if (da >= 270 && da <= 360) {
                    fanData[index++] = cos > xAxis ? xAxis : cos;
                    fanData[index++] = Math.abs(sin) > yAxis ? -yAxis : sin;
                }
                fanData[index++] = 0.7f;
                fanData[index++] = 0.7f;
                fanData[index++] = 0.7f;
                fanData[index++] = 0.7f;
            }
            //add divide line
            for (float v : lineVertex) {
                fanData[index++] = v;
            }
            //add stick
            for (float v : stickVertex) {
                fanData[index++] = v;
            }


            return fanData;
        }

    }

    /**
     * cylinder data
     */
    public static class Cylinder {
        /**
         * generate circle data
         */
        public static float[] generateCircleData(float radium, double angle) {
            int points = (int) ((360.0d / angle + 1 + 1));
            float[] data = new float[points * 4];
            int index=0;
            double arg;
            float yAxis=0.25f;
            //add center point
            data[index++] = 0.0f;
            data[index++] = yAxis;
            data[index++] = 0.0f;
            data[index++] = 0.0f;
            for (int i = 0; i < points - 1; i++) {
                arg = angle * i / 180 * Math.PI;
                data[index++] = (float) (radium * Math.cos(arg));
                data[index++] = yAxis;
                data[index++] = (float) (radium * Math.sin(arg));
                data[index++] = 1.0f;
            }

            return data;
        }

        /**
         * translate y
         */
        public static float[] translateY(float[] srcData,float distance){
            float[] data=new float[srcData.length];
            for (int i = 0; i < srcData.length; i++) {
                data[i]=srcData[i];
            }
            for (int i = 0; i < data.length / 4; i++) {
                data[i*4+2]+=distance;
            }

            return data;
        }

        /**
         * cylinder side data
         *
         * @param radium
         * @param angle
         * @return
         */
        public static float[] generateCylinderSideData(float radium, double angle) {
            int points = ((int) (360.0d / angle + 1) * 2);
            float[] data = new float[points * 4];
            double arg;
            int index = 0;
            float startY = -0.25f;
            float endY = 0.25f;
            for (int i = 0; i < points/2; i++) {
                arg = angle * i / 180 * Math.PI;
                data[index++] = (float) (radium * Math.cos(arg));
                data[index++] = startY;
                data[index++] = (float) (radium * Math.sin(arg));
                data[index++] = 1.0f;

                data[index++] = (float) (radium * Math.cos(arg));
                data[index++] = endY;
                data[index++] = (float) (radium * Math.sin(arg));
                data[index++] = 1.0f;
            }

            return data;
        }

        /**
         * cylinder data
         *
         * @param circleData
         * @param sideData
         * @return
         */
        public static float[] generateCylinderData(float[] circleData, float[] sideData) {
            float[] cylinderData = new float[circleData.length+ sideData.length];
            int index=0;
            for (int i = 0; i < circleData.length; i++) {
                cylinderData[index++] = circleData[i];
            }
            for (int i = 0; i < sideData.length; i++) {
                cylinderData[index++] = sideData[i];
            }
            return cylinderData;

        }

        /**
         *generate double circle data
         */
        public static float[] generateDoubleData(float radium, double angle,float height){
            float[] bottom=generateCircleData(radium,angle);
            float[] top=translateY(bottom,height);

            float[] data=new float[bottom.length+top.length];

            for (int i = 0; i < bottom.length; i++) {
                data[i]=bottom[i];
            }
            for (int i = 0; i < top.length; i++) {
                data[i+bottom.length]=top[i];
            }

            return data;
        }

    }
}
